home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / zoo2 / part08 < prev    next >
Encoding:
Internet Message Format  |  1989-02-01  |  45.3 KB

  1. Subject:  v17i071:  Zoo archive program, Part08/10
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Rahul Dhesi <bsu-cs!dhesi@iuvax.cs.indiana.edu>
  6. Posting-number: Volume 17, Issue 71
  7. Archive-name: zoo2/part08
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 8 (of 10)."
  16. # Wrapped by rsalz@papaya.bbn.com on Thu Feb  2 18:04:04 1989
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f 'portable.c' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'portable.c'\"
  20. else
  21. echo shar: Extracting \"'portable.c'\" \(21282 characters\)
  22. sed "s/^X//" >'portable.c' <<'END_OF_FILE'
  23. X#ifndef LINT
  24. X/* @(#) portable.c 2.24 88/08/24 01:22:06 */
  25. Xstatic char sccsid[]="@(#) portable.c 2.24 88/08/24 01:22:06";
  26. X#endif /* LINT */
  27. X
  28. X#include "options.h"
  29. X/*
  30. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  31. X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
  32. X*/
  33. X/**********************
  34. Xportable.c contains functions needed to make Zoo portable to various
  35. Ximplementations of C.
  36. X
  37. XNote:  Provided a 2's complement machine is used, all functions in
  38. Xthis file are themselves machine-independent and need not be changed
  39. Xwhen implementing Zoo on a different machine.  Some code will choke
  40. Xon 1's complement machines--I think.  
  41. X
  42. XFor machine-dependent declarations see files "machine.h" and "options.h". 
  43. X
  44. XFor machine-dependent functions see file "machine.c"
  45. X*/
  46. X
  47. X#include "zooio.h"
  48. X
  49. X#include "various.h"
  50. X#include "zoofns.h"
  51. X
  52. X#include "machine.h"
  53. X#include "zoo.h"
  54. X#include "debug.h"
  55. X#include "assert.h"
  56. X
  57. X#ifdef NEEDCTYP
  58. X#include <ctype.h>              /* for tolower() */
  59. X#endif
  60. X
  61. X#include "portable.h"
  62. X
  63. X#ifdef TRACE_IO
  64. Xextern int verbose;
  65. X#endif
  66. X
  67. X/* Functions defined for use within this file only.  */
  68. X#ifdef LINT_ARGS
  69. Xlong to_long (BYTE[]);
  70. Xint to_int (BYTE[]);
  71. Xvoid b_to_zooh(struct zoo_header *, BYTE[]);
  72. Xvoid b_to_dir(struct direntry *, BYTE[]);
  73. Xint dir_to_b(BYTE[], struct direntry *);
  74. Xvoid zooh_to_b(BYTE[], struct zoo_header *);
  75. Xvoid splitlong(BYTE[], long);
  76. Xvoid splitint(BYTE[], int);
  77. X#else
  78. Xlong to_long ();
  79. Xint to_int ();
  80. Xvoid b_to_zooh();
  81. Xvoid b_to_dir();
  82. Xint dir_to_b();
  83. Xvoid zooh_to_b();
  84. Xvoid splitlong();
  85. Xvoid splitint();
  86. X#endif
  87. X
  88. X#ifdef TRACE_IO
  89. Xvoid show_h PARMS ((struct zoo_header *));
  90. Xvoid show_dir PARMS ((struct direntry *));
  91. X#endif /* TRACE_IO */
  92. X
  93. Xextern unsigned int crccode;
  94. X
  95. X/************************************************************************/
  96. X/* I/O functions */
  97. X/************************************************************************/
  98. X
  99. X/* some functions get defined only if they aren't already macros */
  100. X
  101. X#ifndef zooread
  102. Xint zooread (file, buffer, count)
  103. XZOOFILE file; char *buffer; int count;
  104. X{ return (fread (buffer, 1, count, file)); }
  105. X#endif /* zooread */
  106. X
  107. X#ifndef FIZ
  108. X#ifndef zoowrite
  109. Xint zoowrite (file, buffer, count)
  110. XZOOFILE file; char *buffer; int count;
  111. X{ 
  112. X    if (file == NULLFILE)
  113. X       return (count);
  114. X    else
  115. X        return (fwrite (buffer, 1, count, file)); 
  116. X}
  117. X#endif /* zoowrite */
  118. X
  119. XZOOFILE zoocreate (fname)
  120. Xchar *fname;
  121. X{ return ((ZOOFILE) fopen (fname, Z_NEW)); }
  122. X
  123. X/* truncates a file -- can be empty */
  124. X/* force use of argument to keep Turbo C happy */
  125. Xint zootrunc (file) ZOOFILE file; {return ((int) file); }
  126. X#endif /* FIZ */
  127. X
  128. X#ifndef zooseek
  129. Xlong zooseek (file, offset, whence)
  130. XZOOFILE file; long offset; int whence;
  131. X{ return (fseek (file, offset, whence)); }
  132. X#endif /* zooseek */
  133. X
  134. XZOOFILE zooopen (fname, option)
  135. Xchar *fname; char *option;
  136. X{ return ((ZOOFILE) fopen (fname, option)); }
  137. X
  138. X#ifndef zootell
  139. Xlong zootell (file)
  140. XZOOFILE file;
  141. X{ return ftell (file); }
  142. X#endif /* zootell */
  143. X
  144. Xint zooclose (file)
  145. XZOOFILE file;
  146. X{ return fclose (file); }
  147. X
  148. X/************************************************************************/
  149. X/*** Following are functions that make up for various implementations ***/
  150. X/*** of C not having certain library routines.                        ***/
  151. X/************************************************************************/
  152. X
  153. X#ifndef FIZ
  154. X#ifndef STRLWR
  155. X/**********************
  156. Xstrlwr() converts a string to lowercase and returns a pointer to the string
  157. X*/
  158. Xchar *strlwr (str)
  159. Xchar *str;
  160. X{
  161. X   register char *s;
  162. X   s = str;
  163. X   while (*s != '\0') {
  164. X      *s = toascii(*s);
  165. X      if (isupper(*s))
  166. X         *s = tolower(*s);
  167. X      s++;
  168. X   }
  169. X   return (str);
  170. X}
  171. X#endif /* STRLWR */
  172. X
  173. X/**********************
  174. Xstrcmpi() compares strings just like strcmp() but it does it without regard to
  175. Xcase.
  176. X*/
  177. Xint strcmpi (s1, s2)
  178. Xregister char *s1, *s2;
  179. X{
  180. X   for ( ; tolower(*s1) == tolower(*s2);  s1++, s2++)
  181. X      if (*s1 == '\0')
  182. X         return(0);
  183. X   return(tolower(*s1) - tolower(*s2));
  184. X}
  185. X
  186. X#ifndef MEMSET
  187. X/**********************
  188. Xmemset() exists in Microsoft C and UNIX System V but not in Xenix.  It sets
  189. Xthe first "cnt" bytes of "dest" to the character "c" and returns a pointer to
  190. X"dest".
  191. X*/
  192. Xchar * memset (dest, c, cnt)
  193. Xchar *dest;
  194. Xint c;
  195. Xunsigned cnt;
  196. X{
  197. X   register unsigned i;
  198. X   for (i = 0; i < cnt; i++) {
  199. X      *(dest + i) = c;
  200. X   }
  201. X   return (dest);
  202. X}
  203. X#endif /* MEMSET */
  204. X
  205. X#ifndef FPUTCHAR
  206. X/**********************
  207. Xfputchar() writes a character to stdout.  It is identical to putchar
  208. Xbut is a function, not a macro.
  209. X*/
  210. Xint fputchar (c)
  211. Xint c;
  212. X{
  213. X   return (fputc(c, stdout));
  214. X}
  215. X#endif /* FPUTCHAR */
  216. X#endif /* FIZ */
  217. X
  218. X/***********************************************************************/
  219. X/*** Following are declarations and functions that are written in a  ***/
  220. X/*** machine-independent way but they implement machine-dependent    ***/
  221. X/*** activities                                                      ***/
  222. X/***********************************************************************/
  223. X
  224. X#ifndef TURBOC
  225. X/**********************
  226. Xto_long() converts four consecutive bytes, in order of increasing
  227. Xsignificance, to a long integer.  It is used to make Zoo independent of the
  228. Xbyte order of the system.  
  229. X*/
  230. Xlong to_long(data)
  231. XBYTE data[];
  232. X{
  233. X   return (long) ((unsigned long) data[0] | ((unsigned long) data[1] << 8) |
  234. X         ((unsigned long) data[2] << 16) | ((unsigned long) data[3] << 24));
  235. X}
  236. X
  237. X#ifndef FIZ
  238. X/********************
  239. Xsplitlong() converts a long integer to four consecutive BYTEs in order
  240. Xof increasing significance.
  241. X*/
  242. Xvoid splitlong(bytes, bigword)
  243. XBYTE bytes[];
  244. Xlong bigword;
  245. X{
  246. X   int i;
  247. X   for (i = 0; i < 4; i++) {
  248. X      bytes[i] = bigword & 0xff;
  249. X      bigword = (unsigned long) bigword >> 8;
  250. X   }
  251. X}     
  252. X#endif /* FIZ */
  253. X
  254. X/*******************
  255. Xsplitint() converts an integer to two consecutive BYTEs in order
  256. Xof increasing significance.
  257. X*/
  258. Xvoid splitint(bytes, word)
  259. XBYTE bytes[];
  260. Xint word;
  261. X{
  262. X   bytes[0] = word & 0xff;
  263. X   word = (unsigned int) word >> 8;
  264. X   bytes[1] = word & 0xff;
  265. X}
  266. X
  267. X/**********************
  268. Xto_int() converts two consecutive bytes, in order of increasing
  269. Xsignificance, to an integer, in a machine-independent manner
  270. X*/
  271. Xint to_int(data)
  272. XBYTE data[];
  273. X{
  274. X   return (int) ((unsigned int) data[0] | ((unsigned int) data[1] << 8));
  275. X}
  276. X
  277. X#else /* else of ifndef TURBOC */
  278. X
  279. Xlong to_long(data)
  280. XBYTE data[];
  281. X{
  282. X   return ( * (long *) data );
  283. X}
  284. X
  285. X#ifndef FIZ
  286. X/********************
  287. Xsplitlong() converts a long integer to four consecutive BYTEs in order
  288. Xof increasing significance.
  289. X*/
  290. Xvoid splitlong(bytes, bigword)
  291. XBYTE bytes[];
  292. Xlong bigword;
  293. X{
  294. X   * (long *) bytes = bigword;
  295. X}
  296. X#endif /* FIZ */
  297. X
  298. X/*******************
  299. Xsplitint() converts an integer to two consecutive BYTEs in order
  300. Xof increasing significance.
  301. X*/
  302. Xvoid splitint(bytes, word)
  303. XBYTE bytes[];
  304. Xint word;
  305. X{
  306. X   * (int *) bytes = word;
  307. X}
  308. X
  309. X/**********************
  310. Xto_int() converts two consecutive bytes, in order of increasing
  311. Xsignificance, to an integer.
  312. X*/
  313. Xint to_int(data)
  314. XBYTE data[];
  315. X{
  316. X   return (*(int *) data);
  317. X}
  318. X
  319. X#endif /* ifndef TURBOC .. else ... */
  320. X
  321. X#ifndef FIZ
  322. X/**********************
  323. XFunction frd_zooh() reads the header of a Zoo archive in a machine-
  324. Xindependent manner, from a ZOOFILE.
  325. X*/
  326. Xint frd_zooh(zoo_header, zoo_file)
  327. Xstruct zoo_header *zoo_header;
  328. XZOOFILE zoo_file;
  329. X{
  330. X   int status;
  331. X   BYTE bytes[SIZ_ZOOH];         /* canonical header representation */
  332. X#ifdef TRACE_IO
  333. X   if (verbose) {
  334. X      printf("At file position [%8lx] ", ftell(zoo_file));
  335. X   }
  336. X#endif
  337. X   status = zooread (zoo_file, (char *) bytes, SIZ_ZOOH);
  338. X   b_to_zooh (zoo_header, bytes);   /* convert array to structure */
  339. X#ifdef TRACE_IO
  340. X   if (verbose) {
  341. X      printf("frd_zooh: reading\n");
  342. X      show_h(zoo_header);
  343. X   }
  344. X#endif
  345. X   if (status < MINZOOHSIZ)
  346. X      return (-1);
  347. X   else
  348. X      return (0);
  349. X}
  350. X#endif /* FIZ */
  351. X
  352. X/**********************
  353. XFunction frd_dir() reads a directory entry in a machine-independent manner,
  354. Xfrom a ZOOFILE.
  355. X*/
  356. Xint frd_dir(direntry, zoo_file) 
  357. Xstruct direntry *direntry; 
  358. XZOOFILE zoo_file;
  359. X{
  360. X   int status;
  361. X   BYTE bytes[MAXDIRSIZE];    /* big enough to hold variable part too */
  362. X
  363. X   /* To simplify things, we read the maximum possible size of the
  364. X   directory entry including the variable size and discard what is not
  365. X   needed */
  366. X#ifdef TRACE_IO
  367. X   if (verbose) {
  368. X      printf("At file position [%8lx] ", ftell(zoo_file));
  369. X   }
  370. X#endif
  371. X   status = zooread (zoo_file, (char *) bytes, MAXDIRSIZE);
  372. X   if (status < SIZ_DIR)
  373. X      return (-1);
  374. X   b_to_dir (direntry, bytes);
  375. X#ifdef TRACE_IO
  376. X   if (verbose) {
  377. X      printf("frd_dir: reading\n");
  378. X      show_dir(direntry);
  379. X   }
  380. X#endif
  381. X   return (0);
  382. X}
  383. X
  384. X#ifndef FIZ
  385. X/***********************
  386. XFunction fwr_dir() writes a directory entry in a machine-independent manner
  387. Xto a ZOOFILE.  Return value is -1 on error, else 0.
  388. X*/
  389. Xint fwr_dir(direntry, zoo_file)
  390. Xstruct direntry *direntry;
  391. XZOOFILE zoo_file;
  392. X{
  393. X   int size;
  394. X   BYTE bytes[MAXDIRSIZE];
  395. X   assert (direntry->type <= 2);
  396. X   size = dir_to_b (bytes, direntry);
  397. X#ifdef TRACE_IO
  398. X   if (verbose) {
  399. X      printf("At file position [%8lx] ", ftell(zoo_file));
  400. X      printf("fwr_dir: writing\n");
  401. X      show_dir(direntry);
  402. X   }
  403. X#endif
  404. X
  405. X   if (zoowrite (zoo_file, (char *) bytes, size) != size)
  406. X      return (-1);
  407. X   else
  408. X      return (0);
  409. X}
  410. X
  411. X/***********************
  412. XFunction fwr_zooh() writes an archive header in a machine-independent manner
  413. Xto a ZOOFILE.  Return value is -1 if error else 0.
  414. X*/
  415. Xint fwr_zooh(zoo_header, zoo_file)
  416. Xstruct zoo_header *zoo_header;
  417. XZOOFILE zoo_file;
  418. X{
  419. X   BYTE bytes[SIZ_ZOOH];    /* was SIZ_DIR -- probably a typo */
  420. X    int hsize;                    /* how much to write -- depends on header type */
  421. X    hsize = MINZOOHSIZ;                /* in case it's an old type 0 header */
  422. X    if (zoo_header->type > 0)        /* but if it's a newer header... */
  423. X        hsize = SIZ_ZOOH;                /* ...size of new type 1 header */
  424. X   zooh_to_b (bytes, zoo_header);
  425. X   if (zoowrite (zoo_file, (char *) bytes, hsize) != hsize)
  426. X      return (-1);
  427. X   else
  428. X      return (0);
  429. X}
  430. X
  431. X/***********************
  432. Xb_to_zooh() converts an array of BYTE to a zoo_header structure.
  433. X*/
  434. Xvoid b_to_zooh (zoo_header, bytes)
  435. Xstruct zoo_header *zoo_header;
  436. XBYTE bytes[];
  437. X{
  438. X   int i;
  439. X   for (i = 0; i < SIZ_TEXT; i++)                     /* copy text */
  440. X      zoo_header->text[i] = bytes[TEXT_I + i];
  441. X   zoo_header->zoo_tag = to_long(&bytes[ZTAG_I]);     /* copy zoo_tag */
  442. X   zoo_header->zoo_start = to_long(&bytes[ZST_I]);    /* copy zoo_start */
  443. X   zoo_header->zoo_minus = to_long(&bytes[ZSTM_I]);
  444. X   zoo_header->major_ver = bytes[MAJV_I];          /* copy versions */
  445. X   zoo_header->minor_ver = bytes[MINV_I];
  446. X    /* default is no archive comment and a header type of 0 */
  447. X    zoo_header->type = 0;
  448. X    zoo_header->acmt_pos = 0L;
  449. X    zoo_header->acmt_len = 0;
  450. X    zoo_header->vdata        = 0;
  451. X    if (zoo_header->zoo_start != FIXED_OFFSET) {            /* if newer header */
  452. X        zoo_header->type = bytes[HTYPE_I];
  453. X        zoo_header->acmt_pos = to_long(&bytes[ACMTPOS_I]);
  454. X        zoo_header->acmt_len = to_int(&bytes[ACMTLEN_I]);
  455. X        zoo_header->vdata        = bytes[HVDATA_I];
  456. X    }
  457. X}
  458. X
  459. X/***********************
  460. Xzooh_to_b() converts a zoo_header structure to an array of BYTE.
  461. X*/
  462. Xvoid zooh_to_b (bytes, zoo_header)
  463. Xstruct zoo_header *zoo_header;
  464. XBYTE bytes[];
  465. X{
  466. X   int i;
  467. X   for (i = 0; i < SIZ_TEXT; i++)                     /* copy text */
  468. X      bytes[TEXT_I + i] = zoo_header->text[i];
  469. X   splitlong (&bytes[ZTAG_I], zoo_header->zoo_tag);
  470. X   splitlong (&bytes[ZST_I], zoo_header->zoo_start);
  471. X   splitlong (&bytes[ZSTM_I], zoo_header->zoo_minus);
  472. X   bytes[MAJV_I] =   zoo_header->major_ver;           /* copy versions */ 
  473. X   bytes[MINV_I] =   zoo_header->minor_ver;
  474. X    bytes[HTYPE_I] =    zoo_header->type;                        /* header type */
  475. X    if (zoo_header->type > 0) {
  476. X        splitlong (&bytes[ACMTPOS_I], zoo_header->acmt_pos);    /* comment posn */
  477. X        splitint (&bytes[ACMTLEN_I], zoo_header->acmt_len);    /* comment len */
  478. X        bytes[HVDATA_I] = zoo_header->vdata;                    /* version data */
  479. X    }
  480. X} /* zooh_to_b() */
  481. X
  482. X/************************
  483. Xdir_to_b() converts a directory entry structure to an array of BYTE.
  484. X*/
  485. Xint dir_to_b (bytes, direntry)
  486. Xstruct direntry *direntry;
  487. XBYTE bytes[];
  488. X{
  489. X   int i;
  490. X   int cursize;
  491. X   int fixsize;
  492. X    int totalsize;
  493. X   splitlong(&bytes[DTAG_I], direntry->zoo_tag);
  494. X   bytes[DTYP_I] = direntry->type ;
  495. X   bytes[PKM_I] = direntry->packing_method ;
  496. X   splitlong(&bytes[NXT_I], direntry->next);
  497. X   splitlong(&bytes[OFS_I], direntry->offset);
  498. X   splitint(&bytes[DAT_I], direntry->date);
  499. X   splitint(&bytes[TIM_I], direntry->time);
  500. X   splitint(&bytes[CRC_I], direntry->file_crc);
  501. X   splitlong(&bytes[ORGS_I], direntry->org_size);
  502. X   splitlong(&bytes[SIZNOW_I], direntry->size_now);
  503. X   bytes[DMAJ_I] = direntry->major_ver;
  504. X   bytes[DMIN_I] = direntry->minor_ver;
  505. X   bytes[DEL_I] = direntry->deleted;
  506. X   bytes[STRUC_I] = direntry->struc;
  507. X   splitlong(&bytes[CMT_I], direntry->comment);
  508. X   splitint(&bytes[CMTSIZ_I], direntry->cmt_size);
  509. X   for (i = 0; i < FNM_SIZ; i++)
  510. X      bytes[FNAME_I + i] = direntry->fname[i];
  511. X   bytes[TZ_I] = NO_TZ;       /* assume unknown */
  512. X   bytes[NAMLEN_I] = 0;
  513. X   bytes[DIRLEN_I] = 0;
  514. X
  515. X   cursize = SIZ_DIR;         /* to count size of directory */
  516. X   fixsize = SIZ_DIR;         /* size of fixed part */
  517. X   assert (direntry->type <= 2);
  518. X   if (direntry->type == 2) { /* handle stuff relevant to type 2 */
  519. X      cursize = SIZ_DIRL;
  520. X      fixsize = SIZ_DIRL;
  521. X      bytes[TZ_I] = direntry->tz;
  522. X      assert(direntry->namlen < 256 && direntry->namlen >= 0);
  523. X        cursize += 2;        /* space for namlen and dirlen */
  524. X      if (direntry->namlen != 0) {
  525. X         bytes[NAMLEN_I] = direntry->namlen;
  526. X         for (i = 0; i < direntry->namlen; i++)
  527. X            bytes[LFNAME_I+i] = direntry->lfname[i];
  528. X         cursize += direntry->namlen;
  529. X      }
  530. X      assert(direntry->dirlen < 256 && direntry->dirlen >= 0);
  531. X      if (direntry->dirlen != 0) {
  532. X         bytes[DIRLEN_I] = direntry->dirlen;
  533. X         for (i = 0; i < direntry->dirlen; i++)
  534. X            bytes[cursize+i] = direntry->dirname[i];
  535. X         cursize += direntry->dirlen;
  536. X      }
  537. X        /* Can't store system id if no namlen & dirlen...BUG!...now fixed.
  538. X            Fortunately, system_id was always 0 so far so it probably
  539. X            got interpreted as namlen=0 and dirlen=0 (2 bytes) */
  540. X      splitint(&bytes[cursize], direntry->system_id);
  541. X        cursize += 2;
  542. X        bytes[cursize] = direntry->fattr & 0xff;                              /* byte 0 */
  543. X        splitint(&bytes[cursize+1], (int) (direntry->fattr >> 8));  /* 1 & 2 */
  544. X        cursize += 3;
  545. X        bytes[cursize] = (direntry->vflag & 0xff);            /* version flag */
  546. X        splitint(&bytes[cursize+1], direntry->version_no);    /* version number */
  547. X        cursize += 3;
  548. X   }
  549. X
  550. X   splitint(&bytes[VARDIRLEN_I], direntry->var_dir_len);
  551. X   assert(cursize == 
  552. X            ((bytes[DIRLEN_I] > 0 || bytes[NAMLEN_I] > 0) ? 2 : 0) +
  553. X            fixsize + bytes[DIRLEN_I] + bytes[NAMLEN_I]
  554. X         );
  555. X
  556. X    /* total size of dir entry is size of fixed part + size of var. part */
  557. X    totalsize = fixsize + direntry->var_dir_len;
  558. X
  559. X   /* Do CRC assuming CRC field is zero, and stuff CRC into field. */
  560. X   splitint(&bytes[DCRC_I], 0);           /* fill with zeroes */
  561. X   crccode = 0;
  562. X   /* avoid mixing pointers to signed and unsigned char */
  563. X   addbfcrc((char *) bytes, totalsize);         /* update CRC */
  564. X   splitint(&bytes[DCRC_I], crccode);
  565. X
  566. X   /* return total length of directory entry */
  567. X   return (totalsize);
  568. X
  569. X} /* dir_to_b() */
  570. X#endif /* FIZ */
  571. X
  572. X/* b_to_dir() converts bytes to directory entry structure.  The CRC of the
  573. Xdirectory bytes, if any, is checked and a zero or nonzero value is returned
  574. Xin direntry->dir_crc according as the check is good or bad */
  575. X
  576. Xvoid b_to_dir(direntry, bytes)
  577. Xstruct direntry *direntry;
  578. XBYTE bytes[];
  579. X{
  580. X   int i;
  581. X    int sysid_offs;            /* temp variable */
  582. X   unsigned int savecrc;
  583. X   direntry->zoo_tag = to_long(&bytes[DTAG_I]);
  584. X   direntry->type = bytes[DTYP_I];
  585. X   direntry->packing_method = bytes[PKM_I];
  586. X   direntry->next = to_long(&bytes[NXT_I]);
  587. X   direntry->offset = to_long(&bytes[OFS_I]);
  588. X   direntry->date = to_int(&bytes[DAT_I]);
  589. X   direntry->time = to_int(&bytes[TIM_I]);
  590. X   direntry->file_crc = to_int(&bytes[CRC_I]);
  591. X   direntry->org_size = to_long(&bytes[ORGS_I]);
  592. X   direntry->size_now = to_long(&bytes[SIZNOW_I]);
  593. X   direntry->major_ver = bytes[DMAJ_I];
  594. X   direntry->minor_ver = bytes[DMIN_I];
  595. X   direntry->deleted = bytes[DEL_I];
  596. X   direntry->struc = bytes[STRUC_I];
  597. X   direntry->comment = to_long(&bytes[CMT_I]);
  598. X   direntry->cmt_size = to_int(&bytes[CMTSIZ_I]);
  599. X    /* for now, versions not implemented */
  600. X    direntry->vflag = 0;
  601. X    direntry->version_no = 0;
  602. X   for (i = 0; i < FNM_SIZ; i++)
  603. X      direntry->fname[i] = bytes[FNAME_I + i];
  604. X
  605. X   /* start by assuming variable part is zero bytes */
  606. X   direntry->var_dir_len = direntry->dir_crc    = 0;
  607. X   direntry->namlen      = direntry->dirlen     = 0;
  608. X   direntry->lfname[0]   = direntry->dirname[0] = '\0';
  609. X   direntry->tz = NO_TZ;               /* assume unknown */
  610. X   direntry->system_id = SYSID_NIX;    /* default system_id if not present */
  611. X    direntry->fattr = NO_FATTR;            /* assume none */
  612. X
  613. X   assert (direntry->type <= 2);
  614. X   if (direntry->type == 2) {
  615. X      direntry->var_dir_len = to_int(&bytes[VARDIRLEN_I]);
  616. X      assert(direntry->var_dir_len <= MAXDIRSIZE);
  617. X      if (direntry->var_dir_len > MAXDIRSIZE)
  618. X         direntry->var_dir_len = MAXDIRSIZE;
  619. X      direntry->tz = bytes[TZ_I];   
  620. X      if (direntry->var_dir_len > 0)
  621. X         direntry->namlen = bytes[NAMLEN_I];
  622. X      if (direntry->var_dir_len > 1)
  623. X         direntry->dirlen = bytes[DIRLEN_I];
  624. X      for (i = 0; i < direntry->namlen; i++)
  625. X         direntry->lfname[i] = bytes[LFNAME_I + i];
  626. X      for (i = 0; i < direntry->dirlen; i++)
  627. X         direntry->dirname[i] = bytes[DIRNAME_I + direntry->namlen + i];
  628. X        sysid_offs = DIRNAME_I + direntry->namlen + i;    /* offset of system id */
  629. X        if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 2) {
  630. X            direntry->system_id = to_int(&bytes[sysid_offs]);
  631. X        }
  632. X        if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 4) {
  633. X            direntry->fattr = ((unsigned long) bytes[sysid_offs + 2]) |
  634. X                                    ((unsigned long) bytes[sysid_offs + 3] << 8) |
  635. X                                    ((unsigned long) bytes[sysid_offs + 4] << 16);
  636. X        }
  637. X        if (direntry->var_dir_len > direntry->namlen + direntry->dirlen + 7) {
  638. X            direntry->vflag = bytes[sysid_offs + 5];
  639. X            direntry->version_no = to_int(&bytes[sysid_offs + 6]);
  640. X        }
  641. X      /* do CRC calculation */
  642. X      savecrc = (unsigned int) to_int(&bytes[DCRC_I]);
  643. X      crccode = 0;
  644. X      splitint(&bytes[DCRC_I], 0);
  645. X      addbfcrc((char *) bytes, SIZ_DIRL + direntry->var_dir_len);
  646. X      direntry->dir_crc = crccode - savecrc;
  647. X   }
  648. X}
  649. X
  650. X#ifdef FILTER
  651. X#define TWOBYTES    2    /* better than literal 2;  figure out why */
  652. X
  653. X/* rdint() reads two bytes from standard input in archive order */
  654. Xint rdint (val)
  655. Xunsigned int *val;
  656. X{
  657. X    BYTE bytes[TWOBYTES];
  658. X    if (zooread (STDIN, bytes, TWOBYTES) == TWOBYTES) {
  659. X        *val = to_int(bytes);
  660. X        return (0);
  661. X    } else
  662. X        return (1);
  663. X}
  664. X
  665. X/* wrint() writes an unsigned int to standard output in archive order */
  666. Xint wrint (val)
  667. Xunsigned int val;
  668. X{
  669. X    BYTE bytes[TWOBYTES];
  670. X    splitint (bytes, val);
  671. X    if (zoowrite (STDOUT, bytes, TWOBYTES) == TWOBYTES)
  672. X        return (0);
  673. X    else
  674. X        return (1);
  675. X}
  676. X#endif /* FILTER */
  677. X
  678. X#ifdef TRACE_IO
  679. X/* dump contents of archive header */
  680. Xvoid show_h (zoo_header)
  681. Xstruct zoo_header *zoo_header;
  682. X{
  683. X   int i;
  684. X   printf ("Header text:\n");
  685. X   for (i = 0; i < SIZ_TEXT;  i++) {      /* ASSUMES ASCII TEXT */
  686. X      int c;
  687. X      c = zoo_header->text[i];
  688. X      if (c >= ' ' && c < 0x7f)
  689. X         putchar (c);
  690. X      else {
  691. X         putchar ('^');
  692. X         putchar (i & 0x40);
  693. X      }
  694. X   }
  695. X   putchar('\n');
  696. X   printf ("zoo_tag = [%8lx] zoo_start = [%8lx] zoo_minus = [%8lx]\n",
  697. X            zoo_header->zoo_tag, zoo_header->zoo_start, 
  698. X            zoo_header->zoo_minus);
  699. X   printf ("major_ver.minor_ver = [%d.%d]\n",
  700. X            zoo_header->major_ver, zoo_header->minor_ver);
  701. X    if (zoo_header->zoo_start != FIXED_OFFSET) {
  702. X        printf ("type = [%d] ", zoo_header->type);
  703. X        printf ("acmt_pos = [%8lx] acmt_len = [%4x] vdata = [%2x]",
  704. X                    zoo_header->acmt_pos, zoo_header->acmt_len, zoo_header->vdata);
  705. X        printf ("\n");
  706. X    }
  707. X   printf ("---------\n");
  708. X}
  709. X
  710. X/* dump contents of directory entry */
  711. Xvoid show_dir (direntry)
  712. Xstruct direntry *direntry;
  713. X{
  714. X   printf ("Directory entry for file [%s][%s]:\n",
  715. X            direntry->fname, direntry->lfname);
  716. X   printf ("tag = [%8lx] type = [%d] PM = [%d] Next = [%8lx] Offset = [%8lx]\n",
  717. X            direntry->zoo_tag, (int) direntry->type, 
  718. X            (int) direntry->packing_method, direntry->next, 
  719. X            direntry->offset);
  720. X   printf ("Orig size = [%ld] Size now = [%ld] dmaj_v.dmin_v = [%d.%d]\n",
  721. X         direntry->org_size, direntry->size_now,
  722. X         (int) direntry->major_ver, (int) direntry->minor_ver);
  723. X   printf ("Struc = [%d] DEL = [%d] comment_offset = [%8lx] cmt_size = [%d]\n",
  724. X         (int) direntry->struc, (int) direntry->deleted, direntry->comment,
  725. X         direntry->cmt_size);
  726. X   printf ("var_dir_len = [%d] TZ = [%d] dir_crc = [%4x]\n",
  727. X            direntry->var_dir_len, (int) direntry->tz, direntry->dir_crc);
  728. X   printf ("system_id = [%d]  dirlen = [%d]  namlen = [%d] fattr=[%24lx]\n", 
  729. X        direntry->system_id, direntry->dirlen, direntry->namlen, direntry->fattr);
  730. X    printf ("vflag = [%4x] version_no = [%4x]\n",
  731. X                direntry->vflag, direntry->version_no);
  732. X   if (direntry->dirlen > 0)
  733. X      printf ("dirname = [%s]\n", direntry->dirname);
  734. X   printf ("---------\n");
  735. X}
  736. X#endif   /* TRACE_IO */
  737. END_OF_FILE
  738. if test 21282 -ne `wc -c <'portable.c'`; then
  739.     echo shar: \"'portable.c'\" unpacked with wrong size!
  740. fi
  741. # end of 'portable.c'
  742. fi
  743. if test -f 'zooext.c' -a "${1}" != "-c" ; then 
  744.   echo shar: Will not clobber existing file \"'zooext.c'\"
  745. else
  746. echo shar: Extracting \"'zooext.c'\" \(21819 characters\)
  747. sed "s/^X//" >'zooext.c' <<'END_OF_FILE'
  748. X#ifndef LINT
  749. X/* @(#) zooext.c 2.21 88/08/24 02:39:04 */
  750. Xstatic char sccsid[]="@(#) zooext.c 2.21 88/08/24 02:39:04";
  751. X#endif /* LINT */
  752. X
  753. X/*
  754. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  755. X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
  756. X*/
  757. X#include "options.h"
  758. X/* Extract file from archive.  Extracts files specified in parameter-list
  759. X   from archive zoo_path.  If none specified, extracts all files from
  760. X   archive. */
  761. X
  762. X#include "zoo.h"
  763. X#include "parse.h"      /* defines struct for parse() */
  764. X
  765. X#include "portable.h"   /* portable I/O definitions */
  766. X#include "machine.h"    /* machine-specific declarations */
  767. X
  768. X#include "zooio.h"
  769. X#include "various.h"
  770. X
  771. X#ifndef NOSIGNAL
  772. X#include <signal.h>
  773. X#endif
  774. X
  775. X#include "zoofns.h"
  776. X
  777. X#ifdef LINT_ARGS
  778. Xint makepath (char *);
  779. Xint needed (char *, struct direntry *, struct zoo_header *);
  780. Xvoid putstr (char *);
  781. X#else
  782. Xint needed ();
  783. Xint makepath ();
  784. Xvoid putstr ();
  785. X#endif
  786. X
  787. X#ifdef FATTR
  788. Xint setfattr PARMS ((char *, unsigned long));
  789. X#endif /* FATTR */
  790. X
  791. Xextern int quiet;
  792. X
  793. X#include "errors.i"
  794. X
  795. X/* Following two are used by ctrl_c() also, hence declared here */
  796. Xchar extfname[LFNAMESIZE];             /* filename of extracted file */
  797. Xchar prtfname[LFNAMESIZE];             /* name of extracted file on screen */
  798. Xstatic ZOOFILE this_file;              /* file to extract */
  799. X
  800. Xstatic int tofile;                     /* true if not pipe or null device */
  801. Xextern unsigned int crccode;
  802. Xextern char *out_buf_adr;              /* address of output buffer */
  803. X
  804. Xvoid zooext(zoo_path, option)
  805. Xchar *zoo_path, *option;
  806. X{
  807. Xchar *whichname;                          /* which name to extract */
  808. Xchar matchname[PATHSIZE];                 /* for pattern matching only */
  809. X#ifndef NOSIGNAL
  810. Xint (*oldsignal)();        /* to save previous SIGINT handler */
  811. X#endif
  812. XZOOFILE zoo_file;                         /* open archive */
  813. Xlong next_ptr;                            /* pointer to within archive */
  814. Xstruct zoo_header zoo_header;             /* header for archive */
  815. Xint status;                               /* error status */
  816. Xint exit_status = 0;                                /* exit status */
  817. Xint error_message;                                /* Whether to give error message */
  818. Xunsigned long disk_space;                 /* disk space left */
  819. Xint matched = 0;                          /* Any files matched? */
  820. Xint overwrite = 0;                        /* force overwrite of files? */
  821. Xint supersede = 0;                                /* supersede newer files? */
  822. Xint needdel = 0;                          /* extract deleted files too */
  823. Xint usepath = 0;                          /* use path for extraction */
  824. Xint todot = 0;                            /* extract relative to . */
  825. Xint badcrc_count = 0;                     /* how many files with bad CRC */
  826. Xint bad_header = 0;                       /* to avoid spurious messages later */
  827. Xlong fiz_ofs = 0;                         /* offset where to start */
  828. Xlong dat_ofs = 0;                                    /* .. and offset of file data */
  829. Xint pipe = 0;                             /* are we piping output? */
  830. Xint null_device = 0;                      /* are we sending to null device? */
  831. X#ifndef PORTABLE
  832. Xint fast_ext = 0;                         /* fast extract as *.?Z? */
  833. Xint alloc_size;                           /* disk allocation unit size */
  834. X#endif
  835. Xstruct direntry direntry;                 /* directory entry */
  836. Xint first_dir = 1;                                /* first dir entry seen? */
  837. X
  838. Xstatic char extract_ver[] = "Zoo %d.%d is needed to extract %s.\n";
  839. Xstatic char no_space[] = "Insufficient disk space to extract %s.\n";
  840. X
  841. Xwhile (*option) {
  842. X   switch (*option) {
  843. X#ifndef PORTABLE
  844. X      case 'z': fast_ext++; break;
  845. X#endif
  846. X      case 'x':
  847. X      case 'e': break;
  848. X      case 'N': null_device++; break;
  849. X      case 'O': overwrite += 2; break;
  850. X      case 'o': overwrite++; break;
  851. X      case 'p': pipe++; break;
  852. X        case 'S': supersede++; break;
  853. X      case 'd': needdel++; break;
  854. X      case 'q': quiet++; break;
  855. X      case '/': usepath++; break;
  856. X      case '.': todot++; break;
  857. X      case '@':     /* if @m,n specified, fiz_ofs = m, dat_ofs = n */
  858. X            {
  859. X                char *comma_pos;
  860. X                ++option;
  861. X                comma_pos = strchr(option, ',');
  862. X                if (comma_pos != NULL) {
  863. X                    dat_ofs = calc_ofs (comma_pos + 1);
  864. X                    *comma_pos = '\0';
  865. X                }
  866. X                fiz_ofs = calc_ofs(option); 
  867. X                goto no_more;
  868. X            }
  869. X      default:
  870. X         prterror ('f', inv_option, *option);
  871. X         /* break; */
  872. X   }
  873. X   option++;
  874. X}
  875. X
  876. Xno_more: /* come from exit in while loop above */
  877. X
  878. X
  879. Xif (overwrite == 1)                 /* must be at least 2 to begin with */
  880. X   overwrite--;
  881. X
  882. Xif (null_device && pipe) {
  883. X   prterror ('f', inv_option, 'p');
  884. X   pipe = 0;
  885. X}
  886. X
  887. Xif (overwrite && pipe)
  888. X   prterror ('w', option_ignored, 'O');
  889. X
  890. X#ifndef PORTABLE
  891. Xif (null_device && fast_ext) {
  892. X   prterror ('w', inv_option, 'N');
  893. X   null_device = 0;
  894. X}
  895. X#endif
  896. X
  897. Xtofile = !pipe && !null_device;     /* sending to actual file */
  898. X
  899. Xzoo_file = zooopen(zoo_path, Z_READ);
  900. X
  901. Xif (zoo_file == NOFILE)
  902. X   prterror ('f', could_not_open, zoo_path);
  903. X
  904. Xif (fiz_ofs != 0L) {                /* if offset specified, start there */
  905. X    prterror ('m', start_ofs, fiz_ofs, dat_ofs);
  906. X   zooseek (zoo_file, fiz_ofs, 0);
  907. X} else {
  908. X   /* read header */
  909. X   frd_zooh (&zoo_header, zoo_file);
  910. X   if ((zoo_header.zoo_start + zoo_header.zoo_minus) != 0L) {
  911. X      prterror ('w', failed_consistency);
  912. X      bad_header++;
  913. X        exit_status = 1;
  914. X   }
  915. X   zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
  916. X}
  917. X
  918. X#ifndef PORTABLE
  919. Xdisk_space = space (0, &alloc_size);         /* remember disk space left */
  920. X#else
  921. Xdisk_space = MAXLONG;              /* infinite disk space */
  922. X#endif
  923. X
  924. X/* if piping output we open the output device just once */
  925. Xif (null_device) {
  926. X   this_file = NULLFILE;
  927. X} else if (pipe)
  928. X   this_file = STDOUT;    /* standard output */
  929. X
  930. Xwhile (1) {
  931. X   frd_dir (&direntry, zoo_file);
  932. X   if (direntry.zoo_tag != ZOO_TAG) {
  933. X      long currpos, zoolength;
  934. X        prterror ('F', invalid_header);
  935. X
  936. X        /* Note:  if header was bad, there's no point trying to find
  937. X            how many more bytes aren't processed -- our seek position is
  938. X            likely very wrong */
  939. X
  940. X        if (!bad_header)
  941. X            if ((currpos = zootell (zoo_file)) != -1L)
  942. X                if (zooseek (zoo_file, 0L, 2) != -1)
  943. X                    if ((zoolength = zootell (zoo_file)) != -1L)
  944. X                        printf (cant_process, zoolength - currpos);              
  945. X        zooexit (1);
  946. X   }
  947. X   if (direntry.next == 0L) {                /* END OF CHAIN */
  948. X      break;                                 /* EXIT on end of chain */
  949. X   }
  950. X    /* when first direntry read, change dat_ofs from abs. pos. to rel. offset */
  951. X    if (first_dir && dat_ofs != 0) {
  952. X        dat_ofs -= direntry.offset;
  953. X        first_dir = 0;
  954. X    }
  955. X   next_ptr = direntry.next + dat_ofs;       /* ptr to next dir entry */
  956. X
  957. X   whichname = choosefname(&direntry);       /* which filename */
  958. X    whichname = strdup(whichname);                /* bug fix */
  959. X   fixfname(whichname);                      /* fix syntax */
  960. X    strcpy (matchname, fullpath (&direntry));    /* get full pathname */
  961. X    if (zoo_header.vdata & VFL_ON)
  962. X        add_version (matchname, &direntry);        /* add version suffix */
  963. X
  964. X/* if extraction to subtree rooted at curr dir, modify pathname */
  965. X#if 0
  966. X#ifdef DIR_LBRACK
  967. X   if (todot && direntry.dirname[0] == *DIR_LBRACK &&
  968. X                direntry.dirname[1] != *CUR_DIR)      {
  969. X      char tmpstr[PATHSIZE];
  970. X      strcpy (tmpstr, DIR_LBRACK);
  971. X      strcat (tmpstr, CUR_DIR);
  972. X      strcat (tmpstr, &direntry.dirname[1]);
  973. X      strcpy (direntry.dirname, tmpstr);
  974. X   }
  975. X#endif
  976. X#endif
  977. X
  978. X   /* hard-coded '/' should be eventually removed */
  979. X   if (todot && *direntry.dirname == '/') { 
  980. X      char tmpstr[PATHSIZE];
  981. X      strcpy(tmpstr, direntry.dirname);
  982. X      strcpy(direntry.dirname,CUR_DIR);
  983. X      strcat(direntry.dirname, tmpstr);
  984. X   }
  985. X
  986. X   /* matchname now holds the full pathname for pattern matching */
  987. X
  988. X   if ( ( (needdel && direntry.deleted) ||
  989. X            (needdel < 2 && !direntry.deleted)
  990. X        ) && needed(matchname, &direntry, &zoo_header)) {
  991. X      matched++;           /* update count of files extracted */
  992. X
  993. X      if (direntry.major_ver > MAJOR_EXT_VER ||
  994. X         (direntry.major_ver == MAJOR_EXT_VER && 
  995. X            direntry.minor_ver > MINOR_EXT_VER)) {
  996. X            prterror ('e', extract_ver, direntry.major_ver, 
  997. X                           direntry.minor_ver, whichname);
  998. X                exit_status = 1;
  999. X            goto loop_again;
  1000. X      }
  1001. X
  1002. X      /* 
  1003. X      If extracting to null device, or if user requested extraction
  1004. X      of entire path, include any directory name in filename.
  1005. X      If extraction to current directory requested, and if extfname
  1006. X      begins with path separator, fix it */
  1007. X
  1008. X      strcpy (extfname, whichname);
  1009. X      if ((usepath || null_device) && direntry.dirlen != 0) {
  1010. X         combine(extfname, direntry.dirname, whichname);
  1011. X         if (usepath > 1 && !null_device)
  1012. X            makepath(direntry.dirname);         /* make dir prefix */
  1013. X      }
  1014. X
  1015. X        strcpy(prtfname, extfname);
  1016. X        if (zoo_header.vdata & VFL_ON)
  1017. X            add_version (prtfname, &direntry);
  1018. X
  1019. X      if (tofile) {
  1020. X         int present = 0;
  1021. X
  1022. X#ifndef PORTABLE
  1023. X         /* 
  1024. X         if Z format (fast) extraction, extension is created as
  1025. X         follows:  for no current extension, new extension is "zzz";
  1026. X         for current extension "a", new extension is "azz";  for 
  1027. X         current extension "ab", new extension is "azb";  and for
  1028. X         current extension "abc", new extension is "azc".
  1029. X         */
  1030. X           
  1031. X         if (fast_ext) {
  1032. X            int length;
  1033. X            struct path_st path_st;
  1034. X            parse (&path_st, extfname);         /* split filename */
  1035. X            strcpy (extfname, path_st.fname);   /* just root filename */
  1036. X            length = strlen (path_st.ext);
  1037. X            strcat (extfname, ".");
  1038. X            if (length == 0)
  1039. X               strcat (extfname, "zzz");        /* no ext -> .zzz */
  1040. X            else if (length == 1) {
  1041. X               strcat (extfname, path_st.ext);
  1042. X               strcat (extfname, "zz");         /* *.?    -> *.?zz */
  1043. X            } else { /* length is 2 or 3 */
  1044. X               if (length == 2)                 /* allow .aa, .ab, etc. */
  1045. X                  path_st.ext[2] = path_st.ext[1];
  1046. X               path_st.ext[1] = 'z';
  1047. X               strcat (extfname, path_st.ext);  /* *.??   -> *.?z? */
  1048. X            }
  1049. X                strcpy(prtfname, direntry.fname);
  1050. X                add_version (prtfname, &direntry);
  1051. X         }
  1052. X#endif   /* ifndef PORTABLE */
  1053. X
  1054. X            /* don't extract if archived file is older than disk copy */
  1055. X            if (!supersede && exists(extfname)) {
  1056. X                unsigned int ddate, dtime;
  1057. X#ifdef GETUTIME
  1058. X                getutime (extfname, &ddate, &dtime);
  1059. X#else
  1060. X                ZOOFILE tfile;
  1061. X                ddate = dtime = 0xffff;                    /* assume maximum */
  1062. X                tfile = zooopen(extfname, Z_READ);
  1063. X                if (tfile == NOFILE)
  1064. X                    goto loop_again;
  1065. X                gettime (tfile, &ddate, &dtime);
  1066. X                zooclose (tfile);
  1067. X#endif
  1068. X                if (cmpnum (direntry.date, direntry.time, ddate, dtime) <= 0) {
  1069. X                    prterror ('m', "%-14s -- skipped\n", prtfname);
  1070. X                    goto loop_again;
  1071. X                }
  1072. X            }
  1073. X
  1074. X         if (overwrite) {
  1075. X            this_file = zoocreate (extfname);
  1076. X#ifdef FATTR
  1077. X                /* if can't open file, and OO option, make it writable first */
  1078. X                if (this_file == NOFILE && overwrite >= 4 && 
  1079. X                        (direntry.fattr >> 22) == 1 && exists(extfname)) {
  1080. X                    setfattr (extfname, (unsigned long) (1L << 7) | direntry.fattr);
  1081. X                    this_file = zoocreate (extfname);
  1082. X                }
  1083. X#endif /* FATTR */
  1084. X         } else {
  1085. X            if (exists (extfname)) {
  1086. X               present = 1;
  1087. X               this_file = NOFILE;
  1088. X            } else
  1089. X               this_file = zoocreate (extfname);
  1090. X         }
  1091. X            error_message = 1;
  1092. X         if (this_file == NOFILE) {
  1093. X            if (present == 1) {      /* if file exists already */
  1094. X                    char ans[20];          /* answer to "Overwrite?" */
  1095. X               do {
  1096. X#ifdef EXT_ANYWAY
  1097. X                  printf ("%s exists; extract anyway? [Yes/No/All] ",
  1098. X                           extfname);
  1099. X#else
  1100. X                  printf ("Overwrite %s (Yes/No/All)? ", extfname);
  1101. X#endif
  1102. X                  fflush (stdin);
  1103. X                  fgets (ans, sizeof(ans), stdin);
  1104. X                  strlwr (ans);
  1105. X               } while (*ans != 'y' && *ans != 'n' && *ans != 'a');
  1106. X   
  1107. X               if (*ans == 'a')
  1108. X                  overwrite++;
  1109. X               if (*ans == 'y' || *ans == 'a') {
  1110. X                  this_file = zoocreate(extfname);
  1111. X                  error_message = 1; /* give error message if open fails */
  1112. X               } else {
  1113. X                  error_message = 0; /* user said 'n', so no error message */
  1114. X               }
  1115. X            } else {
  1116. X               error_message = 1;   /* Real error -- give error message */
  1117. X            }
  1118. X         } /* end if */
  1119. X      } /* end if */
  1120. X
  1121. X      if (this_file == NOFILE) {         /* file couldn't be opened */
  1122. X         if (error_message == 1) {
  1123. X            prterror ('e', "Can't open %s for output.\n", extfname);
  1124. X                exit_status = 1;
  1125. X
  1126. X#ifndef PORTABLE
  1127. X            /* if error was due to full disk, abort */
  1128. X            if (space(0, &alloc_size) < alloc_size)
  1129. X               prterror ('f', disk_full);
  1130. X#endif
  1131. X
  1132. X         }
  1133. X      } else if (zooseek (zoo_file, (direntry.offset + dat_ofs), 0) == -1L) {
  1134. X         prterror ('e', "Could not seek to file data.\n");
  1135. X            exit_status = 1;
  1136. X         close_file (this_file);
  1137. X      } else {
  1138. X#ifndef PORTABLE
  1139. X         /* check msdos's free disk space if we seem to be running low 
  1140. X            (within 1 cluster of being full) */
  1141. X         if (tofile && disk_space < direntry.org_size + alloc_size) {
  1142. X            disk_space = space (0, &alloc_size);
  1143. X            if (disk_space < alloc_size) {
  1144. X               close_file (this_file);
  1145. X               unlink (extfname);
  1146. X               prterror ('f', disk_full);
  1147. X            }              
  1148. X         }
  1149. X#endif
  1150. X         if (tofile && disk_space < direntry.org_size) {
  1151. X#ifdef PORTABLE
  1152. X            ;
  1153. X#else
  1154. X                prterror ('e', no_space, prtfname);
  1155. X            unlink (extfname);               /* delete any created file */
  1156. X#endif   /* portable */
  1157. X
  1158. X         } else { 
  1159. X
  1160. X#ifndef PORTABLE
  1161. X            if (fast_ext) {            /* fast ext -> create header */
  1162. X#ifdef LINT_ARGS
  1163. X               void make_tnh (struct tiny_header *, struct direntry *);
  1164. X#else
  1165. X               void make_tnh();
  1166. X#endif
  1167. X               struct tiny_header tiny_header;
  1168. X               make_tnh(&tiny_header, &direntry);
  1169. X               zoowrite (this_file, (char *) &tiny_header, sizeof(tiny_header));
  1170. X
  1171. X               if (direntry.cmt_size != 0) { /* copy comment */
  1172. X                  long save_pos;
  1173. X                  save_pos = zootell (zoo_file);
  1174. X                  zooseek (zoo_file, direntry.comment, 0);
  1175. X                  getfile (zoo_file, this_file, 
  1176. X                          (long) direntry.cmt_size, 0);
  1177. X                  zooseek (zoo_file, save_pos, 0);
  1178. X               }
  1179. X            }
  1180. X#endif /* ifndef PORTABLE */
  1181. X
  1182. X            crccode = 0;      /* Initialize CRC before extraction */
  1183. X               if (!pipe) {
  1184. X#ifdef PORTABLE
  1185. X                  prterror ('m', "%-14s -- ", prtfname);
  1186. X#else
  1187. X                  if (fast_ext)
  1188. X                     prterror ('m', "%-12s ==> %-12s -- ", 
  1189. X                        prtfname,  extfname);
  1190. X                  else
  1191. X                     prterror ('m', "%-12s -- ", prtfname);
  1192. X#endif /* PORTABLE */
  1193. X
  1194. X               } else {            /* must be pipe */
  1195. X                  prterror ('M',"\n\n********\n%s\n********\n",prtfname);
  1196. X
  1197. X#ifdef SETMODE
  1198. X                  MODE_BIN(this_file);           /* make std output binary so
  1199. X                                                   ^Z won't cause error */
  1200. X#endif
  1201. X               }
  1202. X#ifndef NOSIGNAL
  1203. X            if (tofile)
  1204. X               {
  1205. X                  oldsignal = signal (SIGINT, SIG_IGN);
  1206. X                  if (oldsignal != SIG_IGN) 
  1207. X                     signal (SIGINT, ctrl_c); /* Trap ^C & erase partial file */
  1208. X               }
  1209. X#endif /* not NOSIGNAL */
  1210. X
  1211. X            if (direntry.packing_method == 0)
  1212. X               /* 4th param 1 means CRC update */
  1213. X               status = getfile (zoo_file, this_file, direntry.size_now, 1);
  1214. X
  1215. X#ifndef PORTABLE
  1216. X            else if (fast_ext)
  1217. X               /* 4th param 0 means no CRC update */
  1218. X               status = getfile (zoo_file, this_file, direntry.size_now, 0);
  1219. X#endif
  1220. X
  1221. X            else if (direntry.packing_method == 1) {
  1222. X#ifdef UNBUF_IO
  1223. X                    /* NOT PORTABLE -- DO NOT TRY THIS AT HOME */
  1224. X                    long lseek PARMS ((int, long, int));
  1225. X                    long tell PARMS ((int));
  1226. X                    int this_fd, zoo_fd;
  1227. X            
  1228. X                    /* get file descriptors */
  1229. X                    this_fd = null_device ? -2 : fileno (this_file);
  1230. X                    zoo_fd = fileno (zoo_file);
  1231. X
  1232. X                    zooseek (zoo_file, zootell (zoo_file), 0);    /* synch */
  1233. X                    lseek (zoo_fd, zootell (zoo_file), 0);            /* ..again */
  1234. X                    if (!null_device) {
  1235. X                        zooseek (this_file, zootell (this_file), 0);    /* synch */
  1236. X                        lseek (this_fd, zootell (this_file), 0);        /* ..again */
  1237. X                    }
  1238. X                  status = lzd(zoo_fd, this_fd);            /* uncompress */
  1239. X                    zooseek (zoo_file, tell (zoo_fd), 0);    /* resynch    */
  1240. X                    if (!null_device)
  1241. X                        zooseek (this_file, tell (this_fd), 0);/* resynch    */
  1242. X#else
  1243. X               status = lzd (zoo_file, this_file);     /* uncompress */
  1244. X#endif
  1245. X            } else {
  1246. X               prterror ('e', "File %s:  impossible packing method.\n",
  1247. X                  whichname);
  1248. X                  unlink(extfname);
  1249. X                  goto loop_again;
  1250. X            }
  1251. X
  1252. X
  1253. X#ifndef NOSIGNAL
  1254. X            if (tofile)
  1255. X               signal (SIGINT, oldsignal);
  1256. X#endif /* not NOSIGNAL */
  1257. X
  1258. X#ifdef SETMODE
  1259. X            if (pipe)
  1260. X               MODE_TEXT(this_file);          /* restore text mode */
  1261. X#endif
  1262. X   
  1263. X            if (tofile) {
  1264. X               /* set date/time of file being extracted */
  1265. X#ifdef GETTZ
  1266. X                    void tzadj();
  1267. X                    /* adjust for original timezone */
  1268. X                    tzadj (&direntry);
  1269. X#endif
  1270. X#ifdef NIXTIME
  1271. X               close_file (this_file);
  1272. X               setutime (extfname, direntry.date, direntry.time);
  1273. X#else
  1274. X               settime (this_file, direntry.date, direntry.time);
  1275. X               close_file (this_file);
  1276. X#endif
  1277. X#ifdef FATTR
  1278. X/* Restore file attributes. Bit 23==1 means system-specific; we currently 
  1279. Xdon't recognize this.  Bit 23==0 means use portable format, in which case 
  1280. Xbit 22==0 means ignore attributes.  Thus attributes are ignored if both 
  1281. Xbits 23 and 22 are zero, which is the effect of a zero-filled file 
  1282. Xattribute field.  Currently we restore file attributes if and only if
  1283. Xbit 23==0 and bit 22==1. */
  1284. X
  1285. X                    if ((direntry.fattr >> 22) == 1) {
  1286. X                        setfattr (extfname, direntry.fattr);
  1287. X                    }
  1288. X#endif /* FATTR */
  1289. X            } /* end of if (tofile) ... */
  1290. X            if (status != 0) {
  1291. X                    exit_status = 1;
  1292. X               if (tofile)
  1293. X                  unlink (extfname);
  1294. X               if (status == 1) {
  1295. X                  memerr();
  1296. X               /* To avoid spurious errors due to ^Z being sent to screen,
  1297. X                  we don't check for I/O error if output was piped */
  1298. X               } else if (!pipe && (status == 2 || status == 3)) {
  1299. X                     prterror ('e', no_space, prtfname);
  1300. X               }
  1301. X            } else {
  1302. X               /* file extracted, so update disk space.  */
  1303. X               /* we subtract the original size of the file, rounded
  1304. X                  UP to the nearest multiple of the disk allocation
  1305. X                  size. */
  1306. X#ifndef PORTABLE
  1307. X               {
  1308. X                  unsigned long temp;
  1309. X                  temp = (direntry.org_size + alloc_size) / alloc_size;
  1310. X                  disk_space -= temp * alloc_size;
  1311. X               }
  1312. X#endif
  1313. X
  1314. X               if (
  1315. X#ifndef PORTABLE
  1316. X                          !fast_ext && 
  1317. X#endif
  1318. X                            direntry.file_crc != crccode
  1319. X                        ) {
  1320. X                  badcrc_count++;
  1321. X                        exit_status = 1;
  1322. X                  if (!pipe) {
  1323. X                     if (!null_device)
  1324. X                        prterror ('M', "extracted   ");
  1325. X                     prterror ('w', bad_crc, prtfname);
  1326. X                  }
  1327. X                  else {   /* duplicate to standard error */
  1328. X                     static char stars[] = "\n******\n";
  1329. X                     putstr (stars);
  1330. X                     prterror ('w', bad_crc, prtfname);
  1331. X                     putstr (stars);
  1332. X                     fprintf (stderr, "WARNING:  ");
  1333. X                     fprintf (stderr, bad_crc, prtfname);
  1334. X                  }
  1335. X               } else
  1336. X                  if (!pipe)
  1337. X                     prterror ('M', null_device ? "OK\n" : "extracted\n");
  1338. X
  1339. X            } /* end if */
  1340. X         } /* end if */
  1341. X      } /* end if */
  1342. X   } /* end if */
  1343. X
  1344. Xloop_again:
  1345. X   zooseek (zoo_file, next_ptr, 0); /* ..seek to next dir entry */
  1346. X} /* end while */
  1347. X
  1348. Xclose_file (zoo_file);
  1349. Xif (!matched)
  1350. X   putstr (no_match);
  1351. X
  1352. Xif (badcrc_count) {
  1353. X   prterror ('w', "%d File(s) with bad CRC.\n", badcrc_count);
  1354. X} else if (null_device)
  1355. X   prterror ('m', "Archive seems OK.\n");
  1356. X
  1357. Xzooexit (exit_status);
  1358. X
  1359. X} /* end zooext */
  1360. X
  1361. X/* close_file() */
  1362. X/* closes a file if and only if we aren't sending output to 
  1363. X   a pipe or to the null device */
  1364. X
  1365. Xvoid close_file (file)
  1366. XZOOFILE file;
  1367. X{
  1368. X   if (tofile)
  1369. X      zooclose (file);
  1370. X}
  1371. X
  1372. X/* Ctrl_c() is called if ^C is hit while a file is being extracted.
  1373. X   It closes the files, deletes it, and exits. */
  1374. Xint ctrl_c()
  1375. X{
  1376. X#ifndef NOSIGNAL
  1377. X   signal (SIGINT, SIG_IGN);     /* ignore any more */
  1378. X#endif
  1379. X   zooclose (this_file);
  1380. X   unlink (extfname);
  1381. X   zooexit (1);
  1382. X}
  1383. X
  1384. X#ifndef PORTABLE
  1385. X/* make_tnh copies creates a tiny_header */
  1386. Xvoid make_tnh (tiny_header, direntry)
  1387. Xstruct tiny_header *tiny_header;
  1388. Xstruct direntry *direntry;
  1389. X{
  1390. X   tiny_header->tinytag = TINYTAG;
  1391. X   tiny_header->type = 1;
  1392. X   tiny_header->packing_method = direntry->packing_method;
  1393. X   tiny_header->date = direntry->date;
  1394. X   tiny_header->time = direntry->time;
  1395. X   tiny_header->file_crc = direntry->file_crc;
  1396. X   tiny_header->org_size = direntry->org_size;
  1397. X   tiny_header->size_now = direntry->size_now;
  1398. X   tiny_header->major_ver = direntry->major_ver;
  1399. X   tiny_header->minor_ver = direntry->minor_ver;
  1400. X   tiny_header->cmt_size = direntry->cmt_size;
  1401. X   strcpy (tiny_header->fname, direntry->fname);
  1402. X} 
  1403. X#endif /* ifndef PORTABLE */
  1404. END_OF_FILE
  1405. if test 21819 -ne `wc -c <'zooext.c'`; then
  1406.     echo shar: \"'zooext.c'\" unpacked with wrong size!
  1407. fi
  1408. # end of 'zooext.c'
  1409. fi
  1410. echo shar: End of archive 8 \(of 10\).
  1411. cp /dev/null ark8isdone
  1412. MISSING=""
  1413. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1414.     if test ! -f ark${I}isdone ; then
  1415.     MISSING="${MISSING} ${I}"
  1416.     fi
  1417. done
  1418. if test "${MISSING}" = "" ; then
  1419.     echo You have unpacked all 10 archives.
  1420.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1421. else
  1422.     echo You still need to unpack the following archives:
  1423.     echo "        " ${MISSING}
  1424. fi
  1425. ##  End of shell archive.
  1426. exit 0
  1427.